Skip to content

[AIT-676] Move /api/chat default from core to Vercel layer#35

Open
lawrence-forooghian wants to merge 1 commit intomainfrom
AIT-676-revisit-default-http-route
Open

[AIT-676] Move /api/chat default from core to Vercel layer#35
lawrence-forooghian wants to merge 1 commit intomainfrom
AIT-676-revisit-default-http-route

Conversation

@lawrence-forooghian
Copy link
Copy Markdown
Contributor

@lawrence-forooghian lawrence-forooghian commented Apr 9, 2026

Note: This is a Claude-generated thing but it reflects the result of my thinking and I've read through it all.

Summary

The default HTTP endpoint "/api/chat" is the Vercel AI SDK's default (set by DefaultChatTransport), but we were setting it in our generic core transport. This violates the two-layer architecture principle that the generic layer should know nothing about Vercel.

Make api required on core ClientTransportOptions and apply the "/api/chat" default in the Vercel layer's createClientTransport factory.

To avoid forcing useChat users to call useClientTransport (where api would now be required), useChatTransport now returns a ChatTransportHandle containing both the ChatTransport and the underlying ClientTransport. Previously it only returned the ChatTransport, so callers had no way to access the transport it created internally — they needed a separate useClientTransport call. The handle lets useChat users get the Vercel default without extra configuration, while still having access to the transport for useMessageSync, useActiveTurns, useView, etc.

Options considered

This PR implements Option B below. Feedback welcome on whether Option A would be preferable.

Both diffs are against the Client - React with useChat section of the README.

Option A: Make api required everywhere

Simplest change. Remove the default from core, make api required on ClientTransportOptions. All callers must specify it explicitly. No new types or return type changes.

 import { useChat } from '@ai-sdk/react';
 import { useChannel } from 'ably/react';
 import { useClientTransport, useActiveTurns, useView } from '@ably/ai-transport/react';
 import { useChatTransport, useMessageSync } from '@ably/ai-transport/vercel/react';
 import { UIMessageCodec } from '@ably/ai-transport/vercel';

 function Chat({ chatId, clientId }: { chatId: string; clientId?: string }) {
   const { channel } = useChannel({ channelName: chatId });

-  const transport = useClientTransport({ channel, codec: UIMessageCodec, clientId });
+  const transport = useClientTransport({ channel, codec: UIMessageCodec, clientId, api: '/api/chat' });
   const chatTransport = useChatTransport(transport);

Pros: Simple implementation, explicit, no new abstractions.
Cons: useChat users must specify api even though Vercel's own default transport doesn't require it.

Option B: Preserve the default in the Vercel layer (this PR)

Make api required in core but optional in the Vercel layer. useChatTransport returns both the ChatTransport and the underlying ClientTransport.

 import { useChat } from '@ai-sdk/react';
 import { useChannel } from 'ably/react';
-import { useClientTransport, useActiveTurns, useView } from '@ably/ai-transport/react';
+import { useActiveTurns, useView } from '@ably/ai-transport/react';
 import { useChatTransport, useMessageSync } from '@ably/ai-transport/vercel/react';
-import { UIMessageCodec } from '@ably/ai-transport/vercel';

 function Chat({ chatId, clientId }: { chatId: string; clientId?: string }) {
   const { channel } = useChannel({ channelName: chatId });

-  const transport = useClientTransport({ channel, codec: UIMessageCodec, clientId });
-  const chatTransport = useChatTransport(transport);
+  const { chatTransport, transport } = useChatTransport({ channel, clientId });

Pros: Matches Vercel's own ergonomics (no endpoint needed), fewer imports, fewer lines.
Cons: Was there perhaps some motivation that I've missed — perhaps didactic, perhaps something else? — for requiring users to create the ClientTransport explicitly?

🤖 Generated with Claude Code

@lawrence-forooghian lawrence-forooghian changed the title Move /api/chat default from core to Vercel layer Move /api/chat default from core to Vercel layer Apr 9, 2026
@lawrence-forooghian lawrence-forooghian changed the title Move /api/chat default from core to Vercel layer [AIT-676] Move /api/chat default from core to Vercel layer Apr 9, 2026
@lawrence-forooghian lawrence-forooghian force-pushed the AIT-676-revisit-default-http-route branch from dfe3364 to e3729c8 Compare April 9, 2026 16:54
@lawrence-forooghian lawrence-forooghian marked this pull request as draft April 9, 2026 16:54
@lawrence-forooghian lawrence-forooghian force-pushed the AIT-676-revisit-default-http-route branch from e3729c8 to 4b71a8f Compare April 9, 2026 19:14
Comment thread docs/get-started/vercel-use-chat.md Outdated
Comment thread docs/reference/react-hooks.md Outdated
Comment thread docs/reference/react-hooks.md Outdated
Comment thread docs/reference/react-hooks.md
Comment thread src/vercel/react/use-chat-transport.ts Outdated
Comment thread src/vercel/transport/index.ts Outdated
Comment thread test/vercel/react/use-chat-transport.test.ts Outdated
Comment thread test/vercel/transport/index.test.ts Outdated
@lawrence-forooghian lawrence-forooghian force-pushed the AIT-676-revisit-default-http-route branch from 0646512 to 75c08db Compare April 9, 2026 19:58
@lawrence-forooghian lawrence-forooghian marked this pull request as ready for review April 9, 2026 20:00
@lawrence-forooghian lawrence-forooghian requested review from a team and zknill and removed request for a team April 9, 2026 20:00
@lawrence-forooghian lawrence-forooghian force-pushed the AIT-676-revisit-default-http-route branch from 75c08db to dba1ef8 Compare April 13, 2026 14:40
@github-actions github-actions bot temporarily deployed to staging/pull/35/typedoc April 13, 2026 14:41 Inactive
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 13, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 92.7% 1982 / 2138
🔵 Statements 90.92% 2123 / 2335
🔵 Functions 93.26% 360 / 386
🔵 Branches 77.94% 887 / 1138
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/core/transport/client-transport.ts 91.96% 83.24% 90.62% 93.68% 151, 336, 353, 399, 445, 473, 561-571, 582, 602-615, 773, 830
src/core/transport/types.ts 0% 0% 0% 0%
src/vercel/react/use-chat-transport.ts 100% 100% 100% 100%
Generated in workflow #102 for commit 0ee595e by the Vitest Coverage Report Action

...options,
codec: UIMessageCodec,
// Mirrors the Vercel AI SDK's DefaultChatTransport default.
api: options.api ?? '/api/chat',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this /api/chat string default seems a bit buried now.. should it be some constant in this file or something?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious what value you think this would add? It's only used in this place and isn't intended as a reusable value. If you feel strongly I'm happy to change though

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's pretty hidden / unclear what would happen if you don't pass options.api. How would a developer understand the behaviour of the system?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's documented on VercelClientTransportOptions:

(defaults to "/api/chat")

Copy link
Copy Markdown
Contributor

@zknill zknill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approach looks good, just a note about where we expose the default url string

@lawrence-forooghian lawrence-forooghian force-pushed the AIT-676-revisit-default-http-route branch from dba1ef8 to 37af638 Compare April 14, 2026 17:49
@github-actions github-actions bot temporarily deployed to staging/pull/35/typedoc April 14, 2026 17:50 Inactive
The default HTTP endpoint "/api/chat" is the Vercel AI SDK's default
(set by DefaultChatTransport), but we were setting it in our generic
core transport. This violates the two-layer architecture principle
that the generic layer should know nothing about Vercel.

Make `api` required on core `ClientTransportOptions` and apply the
"/api/chat" default in the Vercel layer's `createClientTransport`
factory.

To avoid forcing useChat users to call `useClientTransport` (where
`api` would now be required), `useChatTransport` now returns a
`ChatTransportHandle` containing both the `ChatTransport` and the
underlying `ClientTransport`. Previously it only returned the
`ChatTransport`, so callers had no way to access the transport it
created internally — they needed a separate `useClientTransport`
call. The handle lets useChat users get the Vercel default without
extra configuration, while still having access to the transport for
`useMessageSync`, `useActiveTurns`, `useView`, etc.

[AIT-676]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants